手機的使用情境,常常會跟網路息息相關。
舉例來說:
這邊在測試的時候,當然是想越貼近實際狀況越好,所以有可能拿實際網站來 Test。
又或者實際網站必須常常改版等等的變因,迫使你自己架一個假網站來 Test。
接下來,我們來看看使用 Robolectric 的話,可以怎樣 Test。
PS:映象中,Robolectric 只能測試 Apache Lib 的網路連線,在你發出的 request還沒到真實 Server 之前,就先攔截下來。
這邊先介紹一些 Robolectric 提供的方法,首先是logHttpRequests
,預設情況為silence,打開後可以在 output 看到一些 log
Robolectric.getFakeHttpLayer().logHttpRequests()
Robolectric.getFakeHttpLayer().silence()
接著是 Robolectric 攔截你的 request 的開關。預設當然是攔截狀態。
Robolectric.getFakeHttpLayer().interceptHttpRequests(boolean)
Robolectric.getFakeHttpLayer().interceptResponseContent(boolean)
Environment:
- Robolectric Ver. 2.4
- Mac OS X 10.10
- Android Studio 1.0.2
總算可以開始測試了!
一樣準備好 SetUp 和 TearDown 方法。
這次只先準備兩個 response,200 和 404。
HttpTest.java1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
| import android.os.Environment;
import com.loopj.android.http.AsyncHttpResponseHandler; import com.loopj.android.http.FileAsyncHttpResponseHandler; import com.loopj.android.http.SyncHttpClient; import com.maxwin.busstop.advance.YumeFile;
import junit.framework.TestCase;
import org.apache.http.Header; import org.apache.http.HttpException; import org.apache.http.HttpRequest; import org.apache.http.HttpResponse; import org.apache.http.ProtocolVersion; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import org.apache.http.entity.InputStreamEntity; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.message.BasicHeader; import org.apache.http.message.BasicHttpResponse; import org.apache.http.util.EntityUtils; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.robolectric.Robolectric; import org.robolectric.RobolectricTestRunner; import org.robolectric.annotation.Config; import org.robolectric.shadows.HttpResponseGenerator; import org.robolectric.tester.org.apache.http.FakeHttpLayer; import org.robolectric.tester.org.apache.http.HttpEntityStub; import org.robolectric.tester.org.apache.http.RequestMatcher;
import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.net.URI; import java.util.ArrayList; import java.util.List;
@RunWith(RobolectricTestRunner.class) @Config(emulateSdk = 18) public class Temp2Test extends TestCase {
HttpResponse successResponse; HttpResponse failResponse;
@Before public void setUp() throws Exception { super.setUp();
ProtocolVersion httpProtocolVersion = new ProtocolVersion("HTTP", 1, 1);
successResponse = new BasicHttpResponse(httpProtocolVersion, 200, "OK"); successResponse.setEntity(new StringEntity("Yume S"));
failResponse = new BasicHttpResponse(httpProtocolVersion, 404, "Not Found"); failResponse.setEntity(new StringEntity("Yume F")); }
@After public void tearDown() throws Exception { Robolectric.clearHttpResponseRules(); Robolectric.clearPendingHttpResponses(); super.tearDown(); } }
|
現在我們開始寫第一組 Test,用 Robolectric 的 addHttpResponseRule。
這一組測試都是側相同的東西,可快速看過。
如果你有興趣的話可以多花一些時間在第 4th and 5th 的測試。
Robolectric.addHttpResponseRule
- (String method, String uri, HttpResponse response)
- (String uri, HttpResponse response)
- (String uri, String response)
- (RequestMatcher requestMatcher, HttpResponse response)
- (RequestMatcher requestMatcher, List<? extends HttpResponse> responses)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
| @Test public void testHttpResponseRule1() throws Exception { HttpClient client = new DefaultHttpClient(); String url = "http://www.test.com/test1.html";
Robolectric.addHttpResponseRule("GET",url,successResponse);
assertFalse(Robolectric.httpRequestWasMade()); assertFalse(Robolectric.httpRequestWasMade(url));
URI uri = new URI( url); HttpGet request = new HttpGet(uri); HttpResponse response;
response = client.execute(request); assertEquals(200,response.getStatusLine().getStatusCode()); assertEquals("Yume S", EntityUtils.toString(response.getEntity()));
assertTrue(Robolectric.httpRequestWasMade()); assertTrue(Robolectric.httpRequestWasMade(url)); }
@Test public void testHttpResponseRule2() throws Exception { HttpClient client = new DefaultHttpClient(); String url = "http://www.test.com/test2.html";
Robolectric.addHttpResponseRule(url,successResponse);
assertFalse(Robolectric.httpRequestWasMade()); assertFalse(Robolectric.httpRequestWasMade(url));
URI uri = new URI( url); HttpGet request = new HttpGet(uri); HttpResponse response;
response = client.execute(request); assertEquals(200,response.getStatusLine().getStatusCode()); assertEquals("Yume S", EntityUtils.toString(response.getEntity()));
assertTrue(Robolectric.httpRequestWasMade()); assertTrue(Robolectric.httpRequestWasMade(url)); }
@Test public void testHttpResponseRule3() throws Exception { HttpClient client = new DefaultHttpClient(); String url = "http://www.test.com/test3.html";
Robolectric.addHttpResponseRule(url,"Yume S");
assertFalse(Robolectric.httpRequestWasMade()); assertFalse(Robolectric.httpRequestWasMade(url));
URI uri = new URI( url); HttpGet request = new HttpGet(uri); HttpResponse response;
response = client.execute(request); assertEquals(200,response.getStatusLine().getStatusCode()); assertEquals("Yume S", EntityUtils.toString(response.getEntity()));
assertTrue(Robolectric.httpRequestWasMade()); assertTrue(Robolectric.httpRequestWasMade(url)); }
@Test public void testHttpResponseRule4() throws Exception { HttpClient client = new DefaultHttpClient(); String url = "http://www.test.com/test4.html";
RequestMatcher requestMatcher = new FakeHttpLayer.DefaultRequestMatcher("GET","http://www.test.com/test4.html"); Robolectric.addHttpResponseRule(requestMatcher,successResponse);
assertFalse(Robolectric.httpRequestWasMade()); assertFalse(Robolectric.httpRequestWasMade(url));
URI uri = new URI( url); HttpGet request = new HttpGet(uri); HttpResponse response;
response = client.execute(request); assertEquals(200,response.getStatusLine().getStatusCode()); assertEquals("Yume S", EntityUtils.toString(response.getEntity()));
assertTrue(Robolectric.httpRequestWasMade()); assertTrue(Robolectric.httpRequestWasMade(url)); }
@Test public void testHttpResponseRule5() throws Exception { HttpClient client = new DefaultHttpClient(); String url = "http://www.test.com/test5.html";
RequestMatcher requestMatcher = new FakeHttpLayer.RequestMatcherBuilder() .host("www.test.com") .path("test5.html") .method("GET"); List<HttpResponse> list = new ArrayList<>(); list.add(successResponse); list.add(failResponse); Robolectric.addHttpResponseRule(requestMatcher,list);
assertFalse(Robolectric.httpRequestWasMade()); assertFalse(Robolectric.httpRequestWasMade(url));
URI uri = new URI( url); HttpGet request = new HttpGet(uri); HttpResponse response;
response = client.execute(request); assertEquals(200,response.getStatusLine().getStatusCode()); assertEquals("Yume S", EntityUtils.toString(response.getEntity()));
response = client.execute(request); assertEquals(404,response.getStatusLine().getStatusCode()); assertEquals("Yume F", EntityUtils.toString(response.getEntity()));
assertTrue(Robolectric.httpRequestWasMade()); assertTrue(Robolectric.httpRequestWasMade(url)); }
|
接著是第二組測試。
連續發了三次 request 之後,分別會收到 200 404 200
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
| @Test public void testPendingHttpResponse1() throws Exception { HttpClient client = new DefaultHttpClient(); String url = "http://www.test.com/testP1.html";
Robolectric.addPendingHttpResponse(successResponse); Robolectric.addPendingHttpResponse(failResponse); Robolectric.addPendingHttpResponse(successResponse);
assertFalse(Robolectric.httpRequestWasMade()); assertFalse(Robolectric.httpRequestWasMade(url));
URI uri = new URI( url); HttpGet request = new HttpGet(uri); HttpResponse response;
response = client.execute(request); assertEquals(200,response.getStatusLine().getStatusCode()); assertEquals("Yume S", EntityUtils.toString(response.getEntity()));
response = client.execute(request); assertEquals(404,response.getStatusLine().getStatusCode()); assertEquals("Yume F", EntityUtils.toString(response.getEntity()));
response = client.execute(request); assertEquals(200,response.getStatusLine().getStatusCode()); assertEquals("Yume S", EntityUtils.toString(response.getEntity()));
assertTrue(Robolectric.httpRequestWasMade()); assertTrue(Robolectric.httpRequestWasMade(url)); }
@Test public void testPendingHttpResponse2() throws Exception { HttpClient client = new DefaultHttpClient(); String url = "http://www.test.com/testP2.html";
HttpResponseGenerator successHttpResponseGenerator = new HttpResponseGenerator() { @Override public HttpResponse getResponse(HttpRequest request) { return successResponse; } }; HttpResponseGenerator failHttpResponseGenerator = new HttpResponseGenerator() { @Override public HttpResponse getResponse(HttpRequest request) { return failResponse; } };
Robolectric.addPendingHttpResponse(successHttpResponseGenerator); Robolectric.addPendingHttpResponse(failHttpResponseGenerator); Robolectric.addPendingHttpResponse(successHttpResponseGenerator);
assertFalse(Robolectric.httpRequestWasMade()); assertFalse(Robolectric.httpRequestWasMade(url));
URI uri = new URI( url); HttpGet request = new HttpGet(uri); HttpResponse response;
response = client.execute(request); assertEquals(200,response.getStatusLine().getStatusCode()); assertEquals("Yume S", EntityUtils.toString(response.getEntity()));
response = client.execute(request); assertEquals(404,response.getStatusLine().getStatusCode()); assertEquals("Yume F", EntityUtils.toString(response.getEntity()));
response = client.execute(request); assertEquals(200,response.getStatusLine().getStatusCode()); assertEquals("Yume S", EntityUtils.toString(response.getEntity()));
assertTrue(Robolectric.httpRequestWasMade()); assertTrue(Robolectric.httpRequestWasMade(url)); }
@Test public void testPendingHttpResponse3() throws Exception { HttpClient client = new DefaultHttpClient(); String url = "http://www.test.com/testP3.html";
Header[] headers = new Header[1]; headers[0] = new BasicHeader("Yume","Dream");
Robolectric.addPendingHttpResponse(200,"Yume S",headers); Robolectric.addPendingHttpResponse(404,"Yume F",headers); Robolectric.addPendingHttpResponse(200,"Yume S",headers);
assertFalse(Robolectric.httpRequestWasMade()); assertFalse(Robolectric.httpRequestWasMade(url));
URI uri = new URI( url); HttpGet request = new HttpGet(uri); HttpResponse response;
response = client.execute(request); assertEquals(200,response.getStatusLine().getStatusCode()); assertEquals("Yume S", EntityUtils.toString(response.getEntity()));
response = client.execute(request); assertEquals(404,response.getStatusLine().getStatusCode()); assertEquals("Yume F", EntityUtils.toString(response.getEntity()));
response = client.execute(request); assertEquals(200,response.getStatusLine().getStatusCode()); assertEquals("Yume S", EntityUtils.toString(response.getEntity()));
assertTrue(Robolectric.httpRequestWasMade()); assertTrue(Robolectric.httpRequestWasMade(url)); }
|
又回來寫第一組測試, 6th 寫法。
先寫一個 ResponseRule。
MyResponseRule.java1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| class MyResponseRule implements HttpEntityStub.ResponseRule { @Override public HttpResponse getResponse() throws HttpException, IOException { HttpResponse response = new BasicHttpResponse(new ProtocolVersion("HTTP", 1, 1), 200, "OK");
response.addHeader(new BasicHeader("Yume","Dream"));
response.setEntity(new StringEntity("Yume S"));
return response; }
@Override public boolean matches(HttpRequest request) { String uri = request.getRequestLine().getUri(); if (uri.equals("http://www.test.com/test6.html")) return true; return false; } }
|
接下來三個測試:
- 用 DefaultHttpClient
- 用 SyncHttpClient 且 request 成功
- 用 SyncHttpClient 且 request 失敗
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
| @Test public void testHttpResponseRule6DefaultHttpClient() throws Exception { HttpClient client = new DefaultHttpClient(); String url = "http://www.test.com/test6.html";
Robolectric.getFakeHttpLayer().addHttpResponseRule(new MyResponseRule());
URI uri = new URI( url); HttpGet request = new HttpGet(uri); HttpResponse response;
response = client.execute(request); assertEquals(200,response.getStatusLine().getStatusCode()); assertEquals("Yume S", EntityUtils.toString(response.getEntity()));
assertTrue(Robolectric.httpRequestWasMade()); assertTrue(Robolectric.httpRequestWasMade(url)); }
@Test public void testHttpResponseRule6SyncHttpClientSuccess() throws Exception { String url = "http://www.test.com/test6.html";
Robolectric.getFakeHttpLayer().addHttpResponseRule(new MyResponseRule());
SyncHttpClient syncHttpClient = new SyncHttpClient(); syncHttpClient.get(url,new AsyncHttpResponseHandler() { @Override public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) { try { String decoded = new String(responseBody, "UTF-8"); assertEquals(200,statusCode); assertEquals("Yume S", decoded); } catch (UnsupportedEncodingException e) { fail("never happen"); } }
@Override public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable error) { fail("never happen"); } });
assertTrue(Robolectric.httpRequestWasMade()); assertTrue(Robolectric.httpRequestWasMade(url)); }
@Test public void testHttpResponseRule6SyncHttpClientFail() throws Exception { String url = "http://www.test.com/test7.html";
Robolectric.getFakeHttpLayer().addHttpResponseRule(new MyResponseRule());
SyncHttpClient syncHttpClient = new SyncHttpClient(); syncHttpClient.get(url,new AsyncHttpResponseHandler() { @Override public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) { fail("never happen"); }
@Override public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable error) { System.out.print("Request Fail Happen"); } }); }
|
最後我們來測一下 Download file。
我先在專案的 assets 中放著我想要測試的 file。
事先當然已知檔案大小以及 checksum。
下載完之後確認檔案大小以及他的完整性。
最後把測試目錄清除。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
| @Test public void testDownloadFile1() throws Exception { String url = "http://www.test.com/test.js";
HttpResponse downloadResponse = new BasicHttpResponse(new ProtocolVersion("HTTP", 1, 1), 200, "OK"); InputStream is = Robolectric.getShadowApplication().getAssets().open("test/async_data_finder_factory.js"); downloadResponse.setEntity(new InputStreamEntity(is,737)); Robolectric.addHttpResponseRule(url,downloadResponse);
String folderName = Robolectric.getShadowApplication().getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath(); YumeFile folder = new YumeFile(folderName); folder.mkdirs(); YumeFile file = new YumeFile(folderName + "/" + "b.js");
SyncHttpClient syncHttpClient = new SyncHttpClient(); syncHttpClient.get(url,new FileAsyncHttpResponseHandler(file) { @Override public void onFailure(int statusCode, Header[] headers, Throwable throwable, File file) { fail("never happen"); }
@Override public void onSuccess(int statusCode, Header[] headers, File file) { YumeFile yumeFile = new YumeFile(file.getAbsolutePath()); assertEquals(yumeFile.checksum(),"065710dfd1e9419deb9507d2e7fdaa98"); assertEquals(737,file.length()); } });
File externalFileFolder = Robolectric.getShadowApplication().getExternalFilesDir("").getParentFile(); externalFileFolder.delete(); }
@Test public void testDownloadFile2() throws Exception { String url = "http://www.test.com/test.ttf";
HttpResponse downloadResponse = new BasicHttpResponse(new ProtocolVersion("HTTP", 1, 1), 200, "OK"); InputStream is = Robolectric.getShadowApplication().getAssets().open("test/RobotoCondensed-Bold.ttf"); downloadResponse.setEntity(new InputStreamEntity(is,737)); Robolectric.addHttpResponseRule(url,downloadResponse);
String folderName = Robolectric.getShadowApplication().getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath(); YumeFile folder = new YumeFile(folderName); folder.mkdirs(); YumeFile file = new YumeFile(folderName + "/" + "c.ttf");
SyncHttpClient syncHttpClient = new SyncHttpClient(); syncHttpClient.get(url,new FileAsyncHttpResponseHandler(file) { @Override public void onFailure(int statusCode, Header[] headers, Throwable throwable, File file) { fail("never happen"); }
@Override public void onSuccess(int statusCode, Header[] headers, File file) { YumeFile yumeFile = new YumeFile(file.getAbsolutePath()); assertEquals("52f9b35f9f7cfa1be2644bcbac61a983",yumeFile.checksum()); assertEquals(141796,file.length()); } });
File externalFileFolder = Robolectric.getShadowApplication().getExternalFilesDir("").getParentFile(); externalFileFolder.delete(); }
|
Source Code At Gists
End